﻿using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using Microsoft.Win32;
using SHomeWorkshop.LunarPresentation.Interfaces;
using SHomeWorkshop.LunarPresentation.Widegets;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class PictureBox : Expression, ICollapsed
    {
        public PictureBox(SubPanel rootPanel, SubPanel parentPanel, Editor editor)
            : base(rootPanel, parentPanel, editor)
        {
            img = new Image();
            img.SnapsToDevicePixels = true;
            img.Cursor = System.Windows.Input.Cursors.Hand;

            img.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(img_MouseRightButtonDown);
            img.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(img_PreviewMouseLeftButtonDown);
            img.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(img_MouseLeftButtonDown);
            img.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(img_MouseLeftButtonUp);

            img.Source = PictureBox.defaultBitmap;
            RenderOptions.SetBitmapScalingMode(img, BitmapScalingMode.NearestNeighbor);

            this.mainBorder.Child = img;

            this.chineseName = "图片框";
        }

        static PictureBox()
        {
            defaultBitmap = new BitmapImage(new Uri("pack://application:,,,/LunarPresentation;component/Resources/Icons/Question.png"));
        }

        public static System.Windows.Media.Imaging.BitmapImage defaultBitmap;

        void img_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            // 接收拖动来的公式。
            Globals.DropExpression(this);
        }

        void img_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                LoadImageFromFile();
                e.Handled = true;
            }
        }

        void img_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor == null) return;
            Editor.SelectedExpression = this;

            //准备拖动公式。
            Globals.dragSourceExpression = this;
            e.Handled = true;
        }

        void img_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Editor != null)
            {
                //Editor.IsScrolling = false;//否则会变成卷动。
                this.Editor.SelectedExpression = this;
                //LoadImageFromFile();//改由右键菜单实现——在编辑器的baseScrolledViewer的右键弹起事件中调用。
            }
            e.Handled = true;
        }

        public void LoadImageFromFile()
        {
            string filename = "";

            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Multiselect = false;
            ofd.Title = Globals.appName + "——请为图片框选择需要的图片：";
            ofd.Filter = "支持的所有图片格式(*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.tiff)|*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.tiff|" +
                "PNG或JPEG图片(*.png;*.jpg;*.jpeg)|*.png;*.jpg;*.jpeg|" +
                "联合图像专家组格式(*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
                "图形交换格式(*.gif)|*.gif|" +
                "W3C 可移植网络图形(*png)|*png|" +
                "标题图像文件(*.tiff)|*.tiff";

            if (ofd.ShowDialog() != true)
            {
                Editor.ParentWindow.Focus();
                return;
            }

            Editor.ParentWindow.Focus();

            filename = ofd.FileName;

            System.IO.FileInfo fileInfo = new FileInfo(filename);

            if (fileInfo.Exists == false)
            {
                System.Windows.MessageBox.Show("文件不存在！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (fileInfo.Length <= 512000)//将图片限制在五百KB以内
            {
                System.Drawing.Image fileImg = System.Drawing.Image.FromFile(filename);
                using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
                {
                    try
                    {
                        if (fileInfo.Extension.ToLower() == ".png")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
                        }
                        else if (fileInfo.Extension.ToLower() == ".jpg" || fileInfo.Extension.ToLower() == ".jpeg")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                        }
                        else if (fileInfo.Extension.ToLower() == ".gif")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
                        }
                        else if (fileInfo.Extension.ToLower() == ".tiff")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
                        }
                        else if (fileInfo.Extension.ToLower() == ".bmp")
                        {
                            fileImg.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
                        }
                        else
                        {
                            return;//不能识别的文件格式。
                        }

                        byte[] b = stream.GetBuffer();
                        string imgDataText = Convert.ToBase64String(b);

                        XmlNode imgNode = this.XmlData.SelectSingleNode("Image");
                        if (imgNode == null)
                        {
                            imgNode = this.XmlData.AppendChild(
                                this.XmlData.OwnerDocument.CreateNode(XmlNodeType.Text, "Image", string.Empty));
                        }

                        #region 准备“撤销”与“重做”数据。
                        ModifingItem mi = new ModifingItem();
                        Action action = new Action(this.ExID, ParentPanel.BasePanel.Children.IndexOf(this),
                            typeof(Expressions.PictureBox).Name, "ImageBase64", imgNode.InnerText, imgDataText);
                        mi.Add(action);
                        #endregion

                        imgNode.InnerText = imgDataText;

                        //添加到“撤销”列表。
                        Editor.Do(mi);

                        //XmlData.SetAttribute("Width", fileImg.Width.ToString());
                        //XmlData.SetAttribute("Height", fileImg.Height.ToString());
                        img.Width = fileImg.Width;
                        img.Height = fileImg.Height;

                        img.Source = new BitmapImage(new Uri(filename));

                        Editor.IsModified = true;
                    }
                    catch (System.Runtime.InteropServices.ExternalException ex)
                    {
                        Dialogs.LunarMsgBox.MsgBoxShow(
                            Globals.appName,
                            "未能载入图片文件。",
                            "该图像以错误的图像格式后缀名保存！\r\n" + ex.Message,
                            ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
            }
            else
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                    Globals.appName,
                    "图片文件太大。",
                    "为防止文档体积过分庞大，本图片框只支持文件尺寸在 500KB 以下的图片！",
                    "请将图片加工一下或另选一张图片。",
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        void textBlock_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
            Commands.Command.SelectInOrEdit();
        }

        void textBlock_MouseLeftButtonDown(object sender,
            System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Editor.SelectedExpression = this;
        }

        private Image img;

        public Image Img
        {
            get { return img; }
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            BuildImage();

            XmlAttribute attrIsCollapsed = this.XmlData.GetAttribute("IsCollapsed");
            if (attrIsCollapsed != null)
            {
                this.isCollapsed = bool.Parse(attrIsCollapsed.Value);
                this.RefreshIsCollapsed();
            }
        }

        public void BuildImage()
        {
            if (this.XmlData == null) return;

            //读取文本
            XmlNode imgNode = this.XmlData.SelectSingleNode("Image");

            //图片可能无数据。
            string imgDataText = imgNode.InnerText;
            BitmapImage bmp = new BitmapImage();

            if (imgDataText != null && imgDataText.Length > 0)
            {
                byte[] b = Convert.FromBase64String(imgDataText);
                bmp.BeginInit();
                bmp.StreamSource = new MemoryStream(b);
                bmp.EndInit();
            }
            else
            {
                bmp = PictureBox.defaultBitmap;
            }

            img.Width = bmp.PixelWidth;
            img.Height = bmp.PixelHeight;
            img.Source = bmp;
        }

        public override string CommentText
        {
            get
            {
                return base.CommentText;
            }
            set
            {
                base.CommentText = value;
                if (isCollapsed && exCollapseMark != null)
                {
                    exCollapseMark.RefreshExCollpseMarkText();
                }
            }
        }

        #region ICollpased接口的实现代码。

        private ExCollapseMark exCollapseMark;

        private bool isCollapsed = false;

        public bool IsCollapsed
        {
            get { return isCollapsed; }
            set
            {
                isCollapsed = value;
                RefreshIsCollapsed();

                this.XmlData.SetAttribute("IsCollapsed", isCollapsed.ToString());

                Editor.IsModified = true;
            }
        }

        private void RefreshIsCollapsed()
        {
            if (isCollapsed)
            {
                if (exCollapseMark == null)
                {
                    exCollapseMark = new ExCollapseMark(this);
                }

                exCollapseMark.RefreshExCollpseMarkText();
                this.mainBorder.Child = exCollapseMark;
            }
            else
            {
                this.mainBorder.Child = img;
                this.exCollapseMark = null;
            }

            this.InvalidateVisual();
        }

        #endregion

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            base.exForeground = value;

            if (this.exCollapseMark != null)
            {
                this.exCollapseMark.UpdateForeground();
            }
        }

        public override void SetProperty(string propertyName, string value)
        {
            if (propertyName == null || propertyName.Length <= 0) return;
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                //case "Indent":
                //    {
                //        this.Indent = int.Parse(value);
                //        break;
                //    }
                case "ImageBase64":
                    {
                        XmlNode imgNode = this.XmlData.SelectSingleNode("Image");
                        imgNode.InnerText = value;
                        BuildImage();
                        break;
                    }
                case "IsCollapsed":
                    {
                        this.IsCollapsed = bool.Parse(value);
                        break;
                    }
            }
        }
    }
}
